/**
 * @file tftp.cpp
 * @author Jakub Trzaskoma
 *
 * Funkcja main serwera TFTP. Odpowieada za przetworzenie listy argumentow wywołania programu i uruchomienie serwera nasłuchującego.
 *
 */

#include <cstdlib>
#include <cstring>
#include "messages/MessageExecutor.h"
#include "messages/MessageACK.h"
#include "messages/MessageError.h"
#include "messages/MessageRRQ.h"
#include "ClientController.h"
#include "FileList.h"
#include "Log.h"
#include "ServerThread.h"
#include "GlobalServer.h"
#include "structures.h"

using namespace std;
using namespace tftp_server;

int main(int argc, char * argv[])
    {
    if (argc < 2)
	{
	cout << "usage: " << argv[0]
		<< " [-p port] [-l log file] [-c fileconfig file] [-x fileconfig changing port] [-k fileconfig change password] [-d][-m][-s][-v][-h] "
		<< endl;
	cout << "try:  `" << argv[0] << " --help` for more help" << endl;
	return 0;
	}
    else if (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))
	{
	cout << "usage: " << argv[0]
		<< " [-p port] [-l log file] [-c fileconfig file] [-x fileconfig changing port] [-k fileconfig change password] [-d][-m][-s][-v][-h]"
		<< endl;
	cout << "options:" << endl;
	cout << "\t" << "-p port" << "\t\t\t\t\t"
		<< "Set server listening port (default: 69)" << endl;
	cout << "\t" << "-l log file" << "\t\t\t\t"
		<< "Set log file  (default: logs.txt)" << endl;
	cout << "\t" << "-c fileconfig file" << "\t\t\t"
		<< "Set file list config file (default: config.txt)" << endl;
	cout << "\t" << "-x fileconfig change port" << "\t\t"
		<< "Set port to connect via TCP for change fileconfig file (default: 2002)"
		<< endl;
	cout << "\t" << "-k fileconfig change password" << "\t\t"
		<< "Set password to change config file (default: pass)" << endl;
	cout << "\t" << "-d" << "\t\t\t\t\t"
		<< "Disable fileconfig changer (default: enable)" << endl;
	cout << "\t" << "-m" << "\t\t\t\t\t"
		<< "Enable MAC client identification (Requires root privileges!)(default: disable)"
		<< endl;
	cout << "\t" << "-s" << "\t\t\t\t\t"
		<< "Enable showing logs on console (default: disable)" << endl;
	cout << "\t" << "-v" << "\t\t\t\t\t"
		<< "Print information about program version" << endl;
	cout << "\t" << "-h" << "\t\t\t\t\t" << "Print help information"
		<< endl;
	cout << "\t" << "--help" << "\t\t\t\t\t" << "Print help information"
		<< endl;
	return 0;
	}
    else if (!strcmp(argv[1], "-v"))
	{
	cout << "version 1.0" << endl;
	return 0;
	}

    //Default settings

    int port = 69;
    int configPort = 2002;
    std::string configFile = "config.txt";
    std::string logFile = "logs.txt";
    std::string conifgPassword = "pass";
    bool isLogOnScreen = false;
    bool isMacCollector = false;
    bool isConfigChanger = true;

    for (int i = 1; i < argc; i++)
	{
	if (!strcmp(argv[i], "-c"))
	    configFile = argv[++i];
	else if (!strcmp(argv[i], "-p"))
	    port = atoi(argv[++i]);
	else if (!strcmp(argv[i], "-l"))
	    logFile = argv[++i];
	else if (!strcmp(argv[i], "-s"))
	    {
	    Loger::getInstance().addLogInformer(new DisplayLogInformer(5));
	    Loger::getInstance().send(Log(
		    "main: Dispaly logs on screen enable!", 3));
	    isLogOnScreen = true;
	    }
	else if (!strcmp(argv[i], "-d"))
	    isConfigChanger = false;
	else if (!strcmp(argv[i], "-m"))
	    {
	    Loger::getInstance().send(Log("main: Mac Collector enable!", 3));
	    isMacCollector = true;
	    }
	else if (!strcmp(argv[i], "-x"))
	    configPort = atoi(argv[++i]);
	else if (!strcmp(argv[i], "-k"))
	    conifgPassword = argv[++i];

	}

    if (isConfigChanger)
	Loger::getInstance().send(Log("main: Config Changer enable!", 3));

    Loger::getInstance().send(Log("main: Log file: " + logFile, 3));
    Loger::getInstance().send(Log("main: Server listining port: " + intToStr(
	    port), 3));
    Loger::getInstance().send(Log("main: Config Changer listining port: "
	    + intToStr(configPort), 3));
    Loger::getInstance().addLogInformer(new FileLogInformer(5, logFile));


    if (FileList::getInstance().setConfigFile(configFile))
	Loger::getInstance().send(Log("main: Fileconfig file loaded: "
		+ configFile, 3));
    else
	Loger::getInstance().send(Log("main: Fileconfig file load fail! "
		+ configFile, 3));

    GlobalServer* globalServer = new GlobalServer(port, configPort,
	    conifgPassword, isMacCollector, isConfigChanger);
    globalServer->listen();

    Loger::getInstance().send(Log("main: Server stopped!", 2));
    delete globalServer;
    return 0;
    }
